// DecisionEngine.java
package org.zjx.core.engine;

import org.zjx.core.*;
import org.zjx.core.client.ActionPuller;
import org.zjx.core.monitor.DecisionMonitor;
import org.zjx.core.state.StateAccessor;
import org.zjx.core.state.StateValidator;
import org.zjx.exception.DecisionException;
import org.zjx.core.model.InterruptEvent;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

/**
 * 决策系统核心引擎 - 游戏AI决策系统的核心实现类，负责管理决策流程、处理中断和验证状态
 *
 * 主要职责详细描述：
 * 1. 决策任务执行流程管理：
 *    - 维护主决策栈(mainStack)和中断决策栈(interruptStack)
 *    - 提供pushMainTask方法将主任务推入决策栈
 *    - 提供nextAction方法获取下一个游戏动作(核心API)
 *    - 内部实现复杂的决策流程控制逻辑
 *
 * 2. 中断事件处理：
 *    - 通过InterruptManager管理中断事件
 *    - 在决策过程中检查并处理中断事件
 *    - 支持不同优先级的中断处理策略
 *
 * 3. 游戏状态验证：
 *    - 使用StateValidator验证游戏状态有效性
 *    - 在关键决策点进行状态验证，防止无效状态导致错误决策
 *
 * 4. 性能监控：
 *    - 通过DecisionMonitor收集决策性能指标
 *    - 记录节点执行时间、错误等信息
 *    - 提供决策过程的可视化跟踪能力
 *
 * 5. 线程安全设计：
 *    - 使用AtomicReference保证引擎状态的原子性更新
 *    - 使用线程安全的PriorityBlockingQueue存储中断事件
 *    - 使用原子变量统计性能指标
 *    - 使用线程池执行决策任务
 *
 * 构造函数详细说明：
 * 1. 默认构造函数：
 *    - 使用Runtime.getRuntime().availableProcessors()作为核心线程数
 *    - 使用默认的任务队列容量(1000)
 *    - 使用默认的任务超时时间(5000毫秒)
 *
 * 2. 全参数构造函数：
 *    - 允许完全自定义所有参数
 *    - 包括线程池配置、超时时间等
 *
 * 线程安全保证：
 * - 所有状态变更都通过原子变量或线程安全数据结构完成
 * - 决策任务在独立的线程池中执行，避免阻塞调用线程
 * - 共享数据访问都进行了适当的同步控制
 */
public final class DecisionEngine implements AutoCloseable {
    // ====================== 配置常量 ======================
    /**
     * 默认任务队列容量 - 1000
     *
     * 设计考虑：
     * - 足够大的容量可以减少任务拒绝的概率
     * - 1000是一个经验值，平衡内存使用和性能
     * - 如果系统负载很高，可能需要调整此值
     */
    private static final int DEFAULT_QUEUE_CAPACITY = 1000;

    /**
     * 关闭超时时间 - 5000毫秒(5秒)
     *
     * 设计考虑：
     * - 给予足够的时间让正在执行的任务完成
     * - 不会过长导致系统关闭过程被延迟
     * - 可以根据实际需要调整
     */
    private static final long SHUTDOWN_TIMEOUT_MS = 5000;

    // ====================== 运行状态 ======================
    /**
     * 引擎状态 - 使用AtomicReference保证原子性更新
     *
     * 状态流转：
     * READY -> RUNNING -> SHUTTING_DOWN -> TERMINATED
     *
     * 状态说明：
     * READY: 引擎已创建但未启动
     * RUNNING: 引擎正常运行中
     * SHUTTING_DOWN: 引擎正在关闭中
     * TERMINATED: 引擎已完全终止
     */
    private final AtomicReference<EngineState> state = new AtomicReference<>(EngineState.READY);

    // ====================== 核心组件 ======================
    /**
     * 决策任务执行线程池
     *
     * 配置参数：
     * - 核心线程数: 由构造函数参数指定
     * - 最大线程数: 核心线程数的2倍
     * - 空闲线程存活时间: 60秒
     * - 任务队列: ArrayBlockingQueue，容量由构造函数参数指定
     * - 线程工厂: EngineThreadFactory，创建命名线程
     * - 拒绝策略: AbortPolicy，直接抛出RejectedExecutionException
     *
     * 设计考虑：
     * - 核心线程数与CPU核心数相关，充分利用多核性能
     * - 最大线程数为核心线程数的2倍，应对突发负载
     * - 合理的空闲线程存活时间平衡资源使用和响应速度
     */
    private final ThreadPoolExecutor executor;

    /**
     * 主决策栈 - 存储正常决策流程中的决策节点
     *
     * 功能说明：
     * - 使用栈结构实现决策流程的回溯和恢复
     * - 支持决策节点的嵌套和组合
     */
    private final DecisionStack mainStack = new DecisionStack();

    /**
     * 中断决策栈 - 存储中断处理流程中的决策节点
     *
     * 功能说明：
     * - 类似于主决策栈，但专门用于中断处理
     * - 支持中断处理流程的嵌套和组合
     */
    private final DecisionStack interruptStack = new DecisionStack();

    /**
     * 中断管理器 - 负责管理和处理中断事件
     *
     * 功能说明：
     * - 提供中断事件的注册、检查和移除功能
     * - 维护中断事件的优先级队列
     */
    private final InterruptManager interruptManager;

    /**
     * 动作拉取器 - 负责从外部源拉取预定义的动作
     *
     * 默认实现：
     * - 使用MemoryActionPuller作为默认实现
     * - 可以替换为其他实现(如数据库或网络拉取器)
     */
    private final ActionPuller actionPuller;

    /**
     * 根决策树 - 决策系统的入口点
     *
     * 功能说明：
     * - 决策树的根节点，包含完整的决策逻辑
     * - 通过遍历决策树生成游戏动作
     */
    private final DecisionTree rootTree;

    /**
     * 状态验证器 - 验证游戏状态的有效性
     *
     * 功能说明：
     * - 在决策前验证状态组件是否有效
     * - 防止无效状态导致错误决策
     */
    private final StateValidator stateValidator;

    /**
     * 决策监控器 - 收集和记录决策性能指标
     *
     * 功能说明：
     * - 记录节点执行时间、错误等信息
     * - 提供决策过程的可视化跟踪能力
     */
    private final DecisionMonitor monitor;

    /**
     * 任务超时时间 - 决策任务的超时时间(毫秒)
     *
     * 设计考虑：
     * - 防止长时间运行的任务阻塞系统
     * - 可以通过getTaskTimeoutMillis()方法动态调整
     */
    private final long taskTimeoutMillis;

    // ====================== 性能指标 ======================
    /**
     * 总请求数 - 使用原子变量保证线程安全
     *
     * 统计范围：
     * - 所有通过nextAction方法发起的决策请求
     */
    private final AtomicLong totalRequests = new AtomicLong();

    /**
     * 成功请求数 - 使用原子变量保证线程安全
     *
     * 统计范围：
     * - 成功完成并返回有效动作的决策请求
     */
    private final AtomicLong successCount = new AtomicLong();

    /**
     * 超时请求数 - 使用原子变量保证线程安全
     *
     * 统计范围：
     * - 因超时而中断的决策请求
     */
    private final AtomicLong timeoutCount = new AtomicLong();

    /**
     * 中断处理次数 - 使用原子变量保证线程安全
     *
     * 统计范围：
     * - 所有被处理的中断事件数量
     */
    private final AtomicLong interruptCount = new AtomicLong();

    /**
     * 构造函数 - 使用默认参数创建决策引擎
     * @param interruptManager 中断管理器
     * @param actionPuller 动作拉取器
     * @param rootTree 根决策树
     * @param stateValidator 状态验证器
     * @param monitor 决策监控器
     */
    public DecisionEngine(InterruptManager interruptManager,
                          ActionPuller actionPuller,
                          DecisionTree rootTree,
                          StateValidator stateValidator,
                          DecisionMonitor monitor) {
        this(interruptManager, actionPuller, rootTree, stateValidator, monitor,
                Runtime.getRuntime().availableProcessors(), 5000, 1000);
    }

    /**
     * 构造函数 - 自定义参数创建决策引擎
     * @param interruptManager 中断管理器
     * @param actionPuller 动作拉取器
     * @param rootTree 根决策树
     * @param stateValidator 状态验证器
     * @param monitor 决策监控器
     * @param corePoolSize 线程池核心线程数
     * @param taskTimeoutMillis 任务超时时间(毫秒)
     * @param maxInterruptTime 最大中断处理时间(毫秒)
     */
    public DecisionEngine(InterruptManager interruptManager,
                          ActionPuller actionPuller,
                          DecisionTree rootTree,
                          StateValidator stateValidator,
                          DecisionMonitor monitor,
                          int corePoolSize,
                          long taskTimeoutMillis,
                          long maxInterruptTime) {
        validateConstructorArgs(interruptManager, actionPuller, rootTree, stateValidator, monitor);
        this.interruptManager = interruptManager;
        this.actionPuller = actionPuller;
        this.rootTree = rootTree;
        this.stateValidator = stateValidator;
        this.monitor = monitor;
        this.taskTimeoutMillis = taskTimeoutMillis;
        this.executor = createExecutor(corePoolSize);
        this.state.set(EngineState.RUNNING);
    }

    /**
     * 验证构造函数参数是否有效
     * @param args 构造函数参数数组
     * @throws IllegalArgumentException 如果任何参数为null
     */
    private void validateConstructorArgs(Object... args) {
        for (Object arg : args) {
            if (arg == null) {
                throw new IllegalArgumentException(
                        "All constructor arguments must be non-null");
            }
        }
    }

    /**
     * 将主任务推入决策栈
     * @param task 要执行的决策节点
     * @param accessor 状态访问器
     * @throws IllegalStateException 如果引擎未运行或状态无效
     */
    public void pushMainTask(DecisionNode task, StateAccessor accessor) {
        checkEngineState();
        validateState(accessor);
        mainStack.push(task, accessor);
        monitor.recordNodeExecution(task, 0);
    }

    /**
     * 获取下一个游戏动作(异步接口)
     *
     * @param clientId 客户端ID，不能为null
     * @param accessor 状态访问器，不能为null
     * @return 包含游戏动作的Optional对象，可能为空
     * @throws DecisionException 如果决策执行失败
     * @throws TimeoutException 如果决策超时
     * @throws IllegalStateException 如果引擎未运行
     * @throws NullPointerException 如果clientId或accessor为null
     */
    public Optional<GameAction> nextAction(String clientId, StateAccessor accessor)
            throws DecisionException, TimeoutException {
        checkEngineState();
        totalRequests.incrementAndGet();

        // 提交决策任务到线程池
        Future<Optional<GameAction>> future = executor.submit(() ->
                processDecision(clientId, accessor)
        );

        try {
            // 等待任务完成，设置超时时间
            Optional<GameAction> action = future.get(
                    getTaskTimeoutMillis(), TimeUnit.MILLISECONDS);
            successCount.incrementAndGet();
            return action;
        } catch (TimeoutException e) {
            handleTimeout(future);
            throw e;
        } catch (ExecutionException e) {
            throw new DecisionException("Decision execution failed", e.getCause());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new DecisionException("Decision interrupted", e);
        }
    }

    /**
     * 关闭决策引擎(实现AutoCloseable接口)
     * 优雅关闭线程池，等待正在执行的任务完成
     */
    @Override
    public void close() {
        if (state.compareAndSet(EngineState.RUNNING, EngineState.SHUTTING_DOWN)) {
            executor.shutdown();
            try {
                // 等待线程池终止，设置超时时间
                if (!executor.awaitTermination(SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                    executor.shutdownNow(); // 强制关闭
                }
                state.set(EngineState.TERMINATED);
            } catch (InterruptedException e) {
                executor.shutdownNow(); // 中断时强制关闭
                Thread.currentThread().interrupt();
            }
        }
    }

    // ========== 私有实现方法 ==========

    /**
     * 处理决策逻辑(核心方法)
     * @param clientId 客户端ID
     * @param accessor 状态访问器
     * @return 游戏动作(可能为null)
     */
    private Optional<GameAction> processDecision(String clientId, StateAccessor accessor) {
        DecisionContext context = createContext(clientId, accessor);
        monitor.recordExecutionTrace(context.getContextId(), new StartNode(), context);

        try {
            validateState(accessor);
            Optional<GameAction> pending = checkPendingActions(clientId);
            if (pending.isPresent()) return pending;

            processInterrupts(accessor);
            return getActionFromStack(accessor)
                    .or(() -> generateNewAction(clientId, accessor));
        } catch (Exception e) {
            monitor.recordError(new ErrorNode(e), e);
            throw e;
        } finally {
            monitor.recordExecutionTrace(context.getContextId(), new EndNode(), context);
        }
    }

    /**
     * 检查是否有待处理的动作
     * @param clientId 客户端ID
     * @return 待处理动作的Optional对象
     */
    private Optional<GameAction> checkPendingActions(String clientId) {
        long start = System.nanoTime();
        try {
            return actionPuller.pullAction(clientId);
        } finally {
            monitor.recordNodeExecution(new PullActionNode(), System.nanoTime() - start);
        }
    }

    /**
     * 处理中断事件
     * @param accessor 状态访问器
     */
    private void processInterrupts(StateAccessor accessor) {
        long start = System.nanoTime();
        try {
            interruptManager.checkInterrupt(accessor).ifPresent(event -> {
                if (shouldHandleInterrupt(event)) {
                    interruptCount.incrementAndGet();
                    interruptStack.push(event.getHandler().get(), accessor);
                    monitor.recordNodeExecution(new InterruptNode(event), System.nanoTime() - start);
                }
            });
        } finally {
            monitor.recordNodeExecution(new InterruptCheckNode(), System.nanoTime() - start);
        }
    }

    /**
     * 从栈中获取动作
     * @param accessor 状态访问器
     * @return 动作的Optional对象
     */
    private Optional<GameAction> getActionFromStack(StateAccessor accessor) {
        return getActiveStack().peek()
                .map(frame -> {
                    long start = System.nanoTime();
                    try {
                        DecisionContext context = createContext("stack", accessor);
                        GameAction action = frame.getCurrentNode().decide(context);
                        monitor.recordNodeExecution(frame.getCurrentNode(), System.nanoTime() - start);
                        return action;
                    } catch (Exception e) {
                        monitor.recordError(frame.getCurrentNode(), e);
                        throw e;
                    }
                });
    }

    /**
     * 生成新动作
     * @param clientId 客户端ID
     * @param accessor 状态访问器
     * @return 动作的Optional对象
     */
    private Optional<GameAction> generateNewAction(String clientId, StateAccessor accessor) {
        long start = System.nanoTime();
        try {
            DecisionContext context = createContext(clientId, accessor);
            GameAction action = rootTree.decide(context);
            if (action != null) {
                actionPuller.registerAction(clientId, action);
            }
            return Optional.ofNullable(action);
        } finally {
            monitor.recordNodeExecution(new RootDecisionNode(), System.nanoTime() - start);
        }
    }

    // ========== 辅助方法 ==========

    /**
     * 创建决策上下文
     * @param clientId 客户端ID
     * @param accessor 状态访问器
     * @return 决策上下文对象
     */
    private DecisionContext createContext(String clientId, StateAccessor accessor) {
        Map<String, Object> params = new ConcurrentHashMap<>();
        params.put("clientId", clientId);
        return new DecisionContext(accessor, params, new ArrayDeque<>());
    }

    /**
     * 创建线程池执行器
     * @param corePoolSize 核心线程数
     * @return 配置好的线程池
     */
    private ThreadPoolExecutor createExecutor(int corePoolSize) {
        return new ThreadPoolExecutor(
                corePoolSize, corePoolSize * 2,  // 核心线程数和最大线程数
                60L, TimeUnit.SECONDS,          // 空闲线程存活时间
                new ArrayBlockingQueue<>(DEFAULT_QUEUE_CAPACITY),  // 任务队列
                new EngineThreadFactory(),      // 线程工厂
                new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略
        );
    }

    /**
     * 验证游戏状态是否有效
     * @param accessor 状态访问器
     * @throws IllegalStateException 如果状态无效
     */
    private void validateState(StateAccessor accessor) {
        if (!stateValidator.validate(accessor)) {
            throw new IllegalStateException("Invalid game state");
        }
    }

    /**
     * 检查引擎运行状态
     * @throws IllegalStateException 如果引擎未运行
     */
    private void checkEngineState() {
        if (!isRunning()) {
            throw new IllegalStateException("Engine is not running. Current state: " + state.get());
        }
    }

    /**
     * 处理任务超时
     * @param future 超时的Future对象
     */
    private void handleTimeout(Future<?> future) {
        timeoutCount.incrementAndGet();
        future.cancel(true);  // 中断正在执行的任务
        monitor.recordError(new TimeoutNode(), new TimeoutException("Decision timeout"));
    }

    /**
     * 判断是否应该处理中断事件
     * @param event 中断事件
     * @return 是否处理该中断
     */
    private boolean shouldHandleInterrupt(InterruptEvent event) {
        return interruptStack.isEmpty() ||
                event.getPriority() == InterruptEvent.Priority.CRITICAL;
    }

    /**
     * 获取当前活动的决策栈
     * @return 主栈或中断栈
     */
    private DecisionStack getActiveStack() {
        return interruptStack.isEmpty() ? mainStack : interruptStack;
    }

    /**
     * 根据中断计数动态调整任务超时时间
     * @return 调整后的超时时间(毫秒)
     */
    private long getTaskTimeoutMillis() {
        return (long) (taskTimeoutMillis * Math.max(0.5, 1 - (interruptCount.get() * 0.01)));
    }

    // ========== 内部类和枚举 ==========

    /**
     * 引擎状态枚举
     */
    private enum EngineState { READY, RUNNING, SHUTTING_DOWN, TERMINATED }

    /**
     * 引擎线程工厂 - 用于创建命名线程
     */
    private static class EngineThreadFactory implements ThreadFactory {
        private final AtomicInteger counter = new AtomicInteger();

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("decision-worker-" + counter.getAndIncrement());
            t.setDaemon(true);  // 设置为守护线程
            t.setUncaughtExceptionHandler((thread, ex) ->
                    System.err.println("Uncaught in " + thread.getName() + ": " + ex));
            return t;
        }
    }

    // ========== 监控标记节点 ==========

    /**
     * 开始节点标记(用于监控)
     */
    private static class StartNode implements DecisionNode {
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "Start"; }
    }

    /**
     * 结束节点标记(用于监控)
     */
    private static class EndNode implements DecisionNode {
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "End"; }
    }

    /**
     * 错误节点标记(用于监控)
     */
    private static class ErrorNode implements DecisionNode {
        private final Exception error;
        ErrorNode(Exception error) { this.error = error; }
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "Error/" + error.getClass().getSimpleName(); }
    }

    /**
     * 超时节点标记(用于监控)
     */
    private static class TimeoutNode implements DecisionNode {
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "Timeout"; }
    }

    /**
     * 拉取动作节点标记(用于监控)
     */
    private static class PullActionNode implements DecisionNode {
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "PullAction"; }
    }

    /**
     * 根决策节点标记(用于监控)
     */
    private static class RootDecisionNode implements DecisionNode {
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "RootDecision"; }
    }

    /**
     * 中断检查节点标记(用于监控)
     */
    private static class InterruptCheckNode implements DecisionNode {
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "InterruptCheck"; }
    }

    /**
     * 中断节点标记(用于监控)
     */
    private static class InterruptNode implements DecisionNode {
        private final InterruptEvent event;
        InterruptNode(InterruptEvent event) { this.event = event; }
        @Override public GameAction decide(DecisionContext ctx) { return null; }
        @Override public String getNodeId() { return "Interrupt/" + event.getEventType(); }
    }

    // ========== Getter方法 ==========

    /**
     * 检查引擎是否正在运行
     * @return 运行状态
     */
    public boolean isRunning() { return state.get() == EngineState.RUNNING; }

    /**
     * 获取总请求数
     * @return 总请求数
     */
    public long getTotalRequests() { return totalRequests.get(); }

    /**
     * 获取成功请求数
     * @return 成功请求数
     */
    public long getSuccessCount() { return successCount.get(); }

    /**
     * 获取超时请求数
     * @return 超时请求数
     */
    public long getTimeoutCount() { return timeoutCount.get(); }

    /**
     * 获取中断处理次数
     * @return 中断处理次数
     */
    public long getInterruptCount() { return interruptCount.get(); }
}